/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.webos.java.rssreader;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.json.JSONObject;
import org.webos.java.base.Frame;
import org.webos.java.base.FrameType;
import org.webos.java.base.NetworkManager;
import org.webos.java.base.RemoteMessage;
import org.webos.java.base.SystemManager;
import org.webos.java.base.grid.GridController;
import org.webos.java.base.grid.GridControllerItem;
import org.webos.java.root.Log;
import org.webos.java.rssreader.FoldersFeeds.FeedItem;
import org.webos.java.rssreader.FoldersFeeds.FolderItem;

/**
 *
 * @author Kostya
 */

@FrameType(code="entries", jsClass="rssreader.Entries")
public class Entries extends Frame<RSSReader>{

    static SimpleDateFormat dateFormat = new SimpleDateFormat("d.MM HH:mm");

    FeedItem feedItem = null;
    FolderItem folderItem = null;

    class EntryItem extends GridControllerItem<String>{

        int id = 0;
        String title = "";
        String url = "";
        String body = "";
        boolean read = false;
        Date publishDate = new Date();
        String feed = "";
        boolean inFolder = false;
        int idFeed = 0;

        public EntryItem(GridController aController, int aID) {
            super(aController, "", Integer.toString(aID));
            id = aID;
        }

        @Override
        public void objectTOJSON(JSONObject aObject) {
            aObject.putOpt("title", SystemManager.prepareTextForView(
                    title==null?"Untitled":title, true));
            aObject.putOpt("url", url);
            aObject.putOpt("body", body);
            aObject.putOpt("read", read);
            aObject.putOpt("feed", SystemManager.prepareTextForView(feed, true));
            aObject.putOpt("inFolder", inFolder);
            aObject.putOpt("publishDate", dateFormat.format(
                    getApplication().getSession().normalizeDate(publishDate)));
        }

    }

    GridController<EntryItem> gridController = 
            new GridController<EntryItem>(this, true,
            getApplication().options.optInt("show_by", 20));

    int loadItems = getApplication().options.optInt("load_total", 100);

    public Entries(RSSReader aRSSReader) {
        super(aRSSReader, aRSSReader.workspace);
        setShowStatus(true);
        setTitle("No items selected");
    }

    @RemoteMessage 
    public void refreshFeeds(JSONObject aObject){
        try {
            if(feedItem!=null){
                int newCount = feedItem.updateThread.forceUpdate();
                if(newCount>0)
                    showFeed(feedItem);
            }
            if(folderItem!=null){
                int newCount = 0;
                for (int i = 0; i < folderItem.getAllChildrenCount(); i++) {
                    FeedItem item = folderItem.getAllChildren(i);
                    newCount += item.updateThread.forceUpdate();
                }
                if(newCount>0){
                    showFolder(folderItem);
                }
            }
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
    }

    @RemoteMessage
    public JSONObject markAsRead(JSONObject aObject){
        synchronized(getApplication().connection){
            try {
                if(feedItem!=null){
                        PreparedStatement st = getApplication().connection.
                                prepareQuery("update ENTRIES set read=true where id_feed=?");
                        st.setInt(1, feedItem.id);
                        st.execute();
                        getApplication().connection.commit();
                        feedItem.addNewItems(-feedItem.unreadCount);
                }
                if(folderItem!=null){
                        PreparedStatement st = getApplication().connection.
                                prepareQuery("update ENTRIES set read=true where id_folder=?");
                        st.setInt(1, folderItem.id);
                        st.execute();
                        getApplication().connection.commit();
                        for (int i = 0; i < folderItem.getAllChildrenCount(); i++) {
                            FeedItem item = folderItem.getAllChildren(i);
                            item.addNewItems(-item.unreadCount);
                        }
                }
            } catch (Throwable t) {
                getApplication().connection.rollback();
                Log.error(this, "Exception thrown: " + t.getMessage());
                t.printStackTrace();
                return NetworkManager.getErrorObject(1211, "Can't mark items as read");
            }
        }
        if(feedItem!=null)
            showFeed(feedItem);
        if(folderItem!=null)
            showFolder(folderItem);
        return null;
    }

    void showFeed(FoldersFeeds.FeedItem aFeedItem){
        feedItem = aFeedItem;
        folderItem = null;
        setTitle(aFeedItem.name);
        setIcon("rss_icn rss_icn_rss");
        aFeedItem.updateStatus();
        refreshItems(aFeedItem.name, "id_feed=?", aFeedItem.id, false, 0, true);
    }

    @RemoteMessage
    public void loadMore(JSONObject aObject){
        if(gridController.getItemCount()<loadItems)
            return;
        if(feedItem!=null){
            refreshItems(feedItem.name, "id_feed=?", feedItem.id, false,
                    gridController.getItemCount(), false);
        }
        if(folderItem!=null){
            refreshItems(folderItem.name, "id_folder=?", folderItem.id, true,
                    gridController.getItemCount(), false);
        }
    }

    void showFolder(FoldersFeeds.FolderItem aFolderItem){
        feedItem = null;
        folderItem = aFolderItem;
        setTitle(aFolderItem.name);
        setIcon("rss_icn rss_icn_folder");
        setStatus("");
        refreshItems(aFolderItem.name, "id_folder=?", aFolderItem.id, true, 0, true);
    }

    private void refreshItems(String aTitle, String aQuery, int aID, 
            boolean aFolder, int aSkip, boolean aClear){
        if(aClear)
            gridController.clear();
        try {
            String andRead = "";
            if(!getApplication().foldersFeeds.showRead)
                andRead = "and read=false ";
            PreparedStatement st = getApplication().connection.
                    prepareQuery("select ENTRIES.id, name, title, body, url, publish_time, read, id_feed " +
                    "from ENTRIES, FEEDS where "+aQuery+" " +
                    "and ENTRIES.id_feed=FEEDS.id " +andRead+
                    "order by publish_time desc limit "+loadItems+" offset "+aSkip);
            st.setInt(1, aID);
            ResultSet rset = st.executeQuery();
            int i = 0;
            while(rset.next()){
                int id = rset.getInt(1);
                EntryItem item = new EntryItem(gridController, id);
                item.inFolder = aFolder;
                if(aFolder)
                    item.feed = rset.getString(2);
                item.title = rset.getString(3);
                item.body = rset.getString(4);
                item.url = rset.getString(5);
                item.publishDate = rset.getTimestamp(6);
                item.read = rset.getBoolean(7);
                item.idFeed = rset.getInt(8);
                gridController.appendItem(item);
            }
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
        getData().putOpt("header", SystemManager.prepareTextForView(aTitle, true));
        sendMessage("updateForm", getData());
        if(aClear)
            gridController.sendGrid();
        else
            gridController.sendGridState();
    }

    @RemoteMessage
    public void openNewWindow(JSONObject aData){
        try {
            EntryItem item = gridController.getItem(aData.optString("id", ""));
            if(item!=null)
                new OneItemViewer(getApplication(), item);
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
    }

    @RemoteMessage
    public void selectionChanged(JSONObject aData){
        boolean read = aData.optBoolean("read", false);
        try {
            EntryItem item = gridController.getItem(aData.optString("id", ""));
            if(item!=null && item.read!=read){
                item.read = read;
                PreparedStatement st = getApplication().connection.
                        prepareQuery("update entries set read=? where id=?");
                st.setBoolean(1, read);
                st.setInt(2, item.id);
                st.execute();
                getApplication().connection.commit();
                FoldersFeeds.FeedItem feedItem = (FeedItem) getApplication().
                        foldersFeeds.controller.findAllItemByID("feed-"+item.idFeed);
                if(feedItem!=null){
                    feedItem.addNewItems(read?-1:1);
                }else{
                    Log.debug(this, "!Can't find feed item in tree");
                }
            }
        } catch (Throwable t) {
            getApplication().connection.rollback();
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
        if(read)
            gridController.selectionChanged(aData);
    }

    @RemoteMessage
    public void showSettings(JSONObject aData){
        new SettingsDialog(getApplication());
    }
}
